package com.tang.juc.ThreadCommunication;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author tlm
 * @version 1.0
 * @date 2020/3/22 20:35
 * Condition 精准的通知和唤醒线程
 * 在上述生产者消费者问题中，如果把线程数量增加到4个（A，B，C，D），
 * A，B，C，D不会按照顺序唤醒。Condition可以实现精准的通知和唤醒线
 * 程。
 * <p>
 * 用Condition实现：A 执行完调用B，B执行完调用C，C执行完调用A
 */
public class ConditionTest {
    public static void main(String[] args) {
        Data3 data3 = new Data3();


        new Thread(()->{
            for(int i = 0 ;i<10;i++){
                data3.printA();
            }
        },"A").start();
        new Thread(()->{
            for(int i = 0 ;i<10;i++){
                data3.printB();
            }
        },"B").start();
        new Thread(()->{
            for(int i = 0 ;i<10;i++){
                data3.printC();
            }
        },"C").start();
    }
}


/*
资源类
 */
class Data3 {

    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    private int num = 1;

    /**
     * A执行，完成后唤醒B
     */
    public void printA() {
        lock.lock();
        //判断=>执行=>通知
        try {
            //判断
            while (num != 1) {
                //等待
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName() + "--------A");
            //执行
            num = 2;
            //通知
            condition2.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }
    /**
     * B执行，完成后唤醒C
     */
    public void printB() {
        lock.lock();
        //判断=>执行=>通知
        try {
            //判断
            while (num != 2) {
                //等待
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName() + "--------B");
            //执行
            num = 3;
            //通知
            condition3.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }
    /**
     * B执行，完成后唤醒A
     */
    public void printC() {
        lock.lock();
        //判断=>执行=>通知
        try {
            //判断
            while (num != 3) {
                //等待
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName() + "--------C");
            //执行
            num = 1;
            //通知
            condition1.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }
}
/*
输出结果：
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
A--------A
B--------B
C--------C
 */
